home *** CD-ROM | disk | FTP | other *** search
- /* memory allocation routines
- *
- * Adapted from alloc routine in K&R; memory statistics and interrupt
- * protection added for use with net package. Must be used in place of
- * standard Turbo-C library routines because the latter check for stack/heap
- * collisions. This causes erroneous failures because process stacks are
- * allocated off the heap.
- */
-
- #include <stdio.h>
- #include <dos.h>
- #include <alloc.h>
- #include "global.h"
- #include "proc.h"
-
- static unsigned long memfail; /* Count of allocation failures */
- static unsigned long allocs; /* Total allocations */
- static unsigned long frees; /* Total frees */
- static unsigned long garbage; /* Total calls to free with garbage arg */
-
- #ifdef LARGEDATA
-
- /**** LARGE DATA MODEL VERSION ****/
-
- union header {
- struct {
- union header huge *ptr;
- unsigned long size;
- } s;
- long l[2];
- };
-
- typedef union header HEADER;
- #define NULLHDR (HEADER huge *)NULL
-
- #define ABLKSIZE (sizeof (HEADER))
-
- static HEADER huge *morecore __ARGS((unsigned nu));
-
- static HEADER base;
- static HEADER huge *allocp = NULLHDR;
- static char huge *heapbase;
- static char huge *heaptop;
- static unsigned long heapsize;
-
- /* Allocate block of 'nb' bytes */
- void *
- malloc(nb)
- unsigned nb;
- {
- register HEADER huge *p, huge *q;
- register unsigned nu;
- char i_state;
-
- if(nb == 0)
- return NULL;
- i_state = dirps();
- /* Round up to full block, then add one for header */
- nu = ((nb + ABLKSIZE - 1) / ABLKSIZE) + 1;
- if ((q = allocp) == NULLHDR){
- base.s.ptr = allocp = q = &base;
- base.s.size = 1;
- }
- for (p = q->s.ptr; ; q = p, p = p->s.ptr){
- if (p->s.size >= nu){
- /* This chunk is at least as large as we need */
- if (p->s.size <= nu + 1){
- /* This is either a perfect fit (size == nu)
- * or the free chunk is just one unit larger.
- * In either case, alloc the whole thing,
- * because there's no point in keeping a free
- * block only large enough to hold the header.
- */
- q->s.ptr = p->s.ptr;
- } else {
- /* Carve out piece from end of entry */
- p->s.size -= nu;
- p += p->s.size;
- p->s.size = nu;
- }
- allocp = q;
- p->s.ptr = p; /* for auditing */
- restore(i_state);
- allocs++;
- return (void *)(p + 1);
- }
- /* Don't call the system for more memory if interrupts
- * are off; we're probably in an interrupt handler
- */
- if (p == allocp && (!i_state || (p = morecore(nu)) == NULLHDR)){
- memfail++;
- restore(i_state);
- return NULL;
- }
- }
- }
- /* Get more memory from the system and put it on the heap */
- static HEADER huge *
- morecore(nu)
- unsigned nu;
- {
- register char huge *cp;
- register HEADER huge *up;
-
- /* Before calling main, the Turbo startup routines call malloc to
- * save the environment. In turn this calls morecore, all before we
- * get a chance to call grabcore. Hence the null test for heaptop.
- */
- if(heaptop != NULL && (char huge *)sbrk(0) >= heaptop)
- return NULLHDR; /* Don't let it overwrite stack */
- if ((int)(cp = (char huge *)sbrk(nu * ABLKSIZE)) == -1)
- return NULLHDR;
- up = (HEADER *)cp;
- up->s.size = nu;
- up->s.ptr = up; /* satisfy audit */
- free((void *)(up + 1));
- return allocp;
- }
- /* Grab the specified amount of memory from the system, if available,
- * and place it on the heap
- */
- unsigned long
- grabcore(size)
- unsigned long size;
- {
- register HEADER huge *up;
-
- /* Find out where the break is */
- heapbase = (char huge *)sbrk(0);
- /* Now try to get the requested amount, or as much as possible
- * below that
- */
- while((int)brk(heapbase+size) == -1)
- size -= 256;
-
- heapsize = size;
- heaptop = (char huge *)sbrk(0);
-
- /* Initialize the heap pointers */
- if (allocp == NULLHDR){
- base.s.ptr = allocp = &base;
- base.s.size = 1;
- }
- up = (HEADER *)heapbase;
- up->s.size = heapsize / sizeof(HEADER);
- up->s.ptr = up; /* satisfy audit */
- free((void *)(up + 1));
- return heapsize;
- }
-
- /* Put memory block back on heap */
- void
- free(blk)
- void *blk;
- {
- register HEADER huge *p, huge *q;
- unsigned short huge *ptr;
- char i_state;
-
- if(blk == NULL)
- return; /* Required by ANSI */
- i_state = dirps();
- p = (HEADER huge *)blk - 1;
- /* Audit check */
- if(p->s.ptr != p){
- ptr = (unsigned short *)&blk;
- printf("WARNING!! freeing garbage (0x%lx) pc = 0x%x %x proc %s\n",ptol(blk),
- ptr[-1],ptr[-2],Curproc->name);
- garbage++;
- restore(i_state);
- return;
- }
- /* Search the free list looking for the right place to insert */
- for(q = allocp; !(p > q && p < q->s.ptr); q = q->s.ptr){
- /* Highest address on circular list? */
- if(q >= q->s.ptr && (p > q || p < q->s.ptr))
- break;
- }
- if(p + p->s.size == q->s.ptr){
- /* Combine with front of this entry */
- p->s.size += q->s.ptr->s.size;
- p->s.ptr = q->s.ptr->s.ptr;
- } else {
- /* Link to front of this entry */
- p->s.ptr = q->s.ptr;
- }
- if(q + q->s.size == p){
- /* Combine with end of this entry */
- q->s.size += p->s.size;
- q->s.ptr = p->s.ptr;
- } else {
- /* Link to end of this entry */
- q->s.ptr = p;
- }
- allocp = q;
- restore(i_state);
- frees++;
- }
-
- #ifdef notdef /* Not presently used */
- /* Move existing block to new area */
- void *
- realloc(area,size)
- void *area;
- unsigned size;
- {
- unsigned osize;
- HEADER huge *hp;
- char huge *cp;
- char i_state;
-
- hp = ((HEADER *)area) - 1;
- osize = (hp->s.size -1) * ABLKSIZE;
-
- /* Make sure nobody else comes in and takes it */
- i_state = dirps();
- free(area);
- if((cp = malloc(size)) != NULL && cp != area)
- memcpy((char *)cp,(char *)area,size>osize? osize : size);
- restore(i_state);
- return cp;
- }
- #endif
- /* Allocate block of cleared memory */
- void *
- calloc(nelem,size)
- unsigned nelem; /* Number of elements */
- unsigned size; /* Size of each element */
- {
- register unsigned i;
- register char *cp;
-
- i = nelem * size;
- if((cp = malloc(i)) != NULL)
- memset(cp,0,i);
- return cp;
- }
- /* Print free list map */
- int
- memstat(argc,argv,envp)
- int argc;
- char *argv[];
- void *envp;
- {
- HEADER huge *p;
- unsigned long total = 0;
- int i = 0;
-
- for(p = base.s.ptr;p != &base;p = p->s.ptr){
- total += p->s.size * sizeof(HEADER);
- printf("%5lx %6lu",ptol((void *)p),p->s.size * ABLKSIZE);
- if(++i == 4){
- i = 0;
- putchar('\n');
- } else
- printf(" | ");
- }
- if(i != 0)
- putchar('\n');
- printf("heap base %lx size %lu avail %lu (%lu%%) coreleft %lu\n",
- ptol((void *)heapbase),heapsize,total,100L*total/heapsize,
- coreleft());
- printf("allocs %lu frees %lu (diff %lu) mfails %lu garbage %lu\n",
- allocs,frees,allocs-frees,memfail,garbage);
- return 0;
- }
- #else /* not LARGEDATA */
-
- /**** SMALL DATA MODEL VERSION ****/
-
- union header {
- struct {
- union header *ptr;
- unsigned int size;
- } s;
- long l;
- };
-
- typedef union header HEADER;
- #define NULLHDR (HEADER *)NULL
-
- #define ABLKSIZE (sizeof (HEADER))
-
- static HEADER *morecore __ARGS((unsigned nu));
-
- static HEADER base;
- static HEADER *allocp = NULLHDR;
- static char *heapbase;
- static char *heaptop;
- static unsigned long heapsize;
-
- /* Allocate block of 'nb' bytes */
- void *
- malloc(nb)
- unsigned nb;
- {
- register HEADER *p, *q;
- register unsigned nu;
- char i_state;
-
- if(nb == 0)
- return NULL;
- i_state = dirps();
- /* Round up to full block, then add one for header */
- nu = ((nb + ABLKSIZE - 1) / ABLKSIZE) + 1;
- if ((q = allocp) == NULLHDR){
- base.s.ptr = allocp = q = &base;
- base.s.size = 1;
- }
- for (p = q->s.ptr; ; q = p, p = p->s.ptr){
- if (p->s.size >= nu){
- /* This chunk is at least as large as we need */
- if (p->s.size <= nu + 1){
- /* This is either a perfect fit (size == nu)
- * or the free chunk is just one unit larger.
- * In either case, alloc the whole thing,
- * because there's no point in keeping a free
- * block only large enough to hold the header.
- */
- q->s.ptr = p->s.ptr;
- } else {
- /* Carve out piece from end of entry */
- p->s.size -= nu;
- p += p->s.size;
- p->s.size = nu;
- }
- allocp = q;
- p->s.ptr = p; /* for auditing */
- restore(i_state);
- allocs++;
- return (void *)(p + 1);
- }
- if (p == allocp && (p = morecore(nu)) == NULLHDR){
- memfail++;
- restore(i_state);
- return NULL;
- }
- }
- }
- /* Get more memory from the system and put it on the heap */
- static HEADER *
- morecore(nu)
- unsigned nu;
- {
- register char *cp;
- register HEADER *up;
-
- /* Before calling main, the Turbo startup routines call malloc to
- * save the environment. In turn this calls morecore, all before we
- * get a chance to call grabcore. Hence the null test for heaptop.
- */
- if(heaptop != NULL && (char *)sbrk(0) >= heaptop)
- return NULLHDR; /* Don't let it overwrite stack */
- if ((int)(cp = (char *)sbrk(nu * ABLKSIZE)) == -1)
- return NULLHDR;
- up = (HEADER *)cp;
- up->s.size = nu;
- up->s.ptr = up; /* satisfy audit */
- free((void *)(up + 1));
- return allocp;
- }
- /* Grab the specified amount of memory from the system, if available,
- * and place it on the heap
- */
- unsigned long
- grabcore(size)
- unsigned long size;
- {
- register HEADER *up;
-
- /* Find out where the break is */
- heapbase = (char *)sbrk(0);
-
- /* Now try to push it as high as possible */
- while(brk(heapbase+size) == -1)
- size -= 16;
-
- heapsize = size;
- heaptop = (char *)sbrk(0);
-
- /* Initialize the heap pointers */
- if (allocp == NULLHDR){
- base.s.ptr = allocp = &base;
- base.s.size = 1;
- }
- up = (HEADER *)heapbase;
- up->s.size = heapsize / sizeof(HEADER);
- up->s.ptr = up; /* satisfy audit */
- free((void *)(up + 1));
- return heapsize;
- }
-
- /* Put memory block back on heap */
- void
- free(blk)
- void *blk;
- {
- register HEADER *p,*q;
- unsigned short *ptr;
- char i_state;
-
- if(blk == NULL)
- return; /* Required by ANSI */
- i_state = dirps();
- p = (HEADER *)blk - 1;
- /* Audit check */
- if(p->s.ptr != p){
- ptr = (unsigned short *)&blk;
- printf("WARNING!! freeing garbage (0x%lx) pc = 0x%x %x proc %s\n",ptol(blk),
- ptr[-1],ptr[-2],Curproc->name);
- garbage++;
- restore(i_state);
- return;
- }
- /* Search the free list looking for the right place to insert */
- for(q = allocp; !(p > q && p < q->s.ptr); q = q->s.ptr){
- /* Highest address on circular list? */
- if(q >= q->s.ptr && (p > q || p < q->s.ptr))
- break;
- }
- if(p + p->s.size == q->s.ptr){
- /* Combine with front of this entry */
- p->s.size += q->s.ptr->s.size;
- p->s.ptr = q->s.ptr->s.ptr;
- } else {
- /* Link to front of this entry */
- p->s.ptr = q->s.ptr;
- }
- if(q + q->s.size == p){
- /* Combine with end of this entry */
- q->s.size += p->s.size;
- q->s.ptr = p->s.ptr;
- } else {
- /* Link to end of this entry */
- q->s.ptr = p;
- }
- allocp = q;
- restore(i_state);
- frees++;
- }
-
- #ifdef notdef /* Not presently used */
- /* Move existing block to new area */
- void *
- realloc(area,size)
- void *area;
- unsigned size;
- {
- unsigned osize;
- HEADER *hp;
- char *cp;
- char i_state;
-
- hp = ((HEADER *)area) - 1;
- osize = (hp->s.size -1) * ABLKSIZE;
-
- /* Make sure nobody else comes in and takes it */
- i_state = dirps();
- free(area);
- if((cp = malloc(size)) != NULL && cp != area)
- memcpy((char *)cp,(char *)area,size>osize? osize : size);
- restore(i_state);
- return cp;
- }
- #endif
- /* Allocate block of cleared memory */
- void *
- calloc(nelem,size)
- unsigned nelem; /* Number of elements */
- unsigned size; /* Size of each element */
- {
- register unsigned i;
- register char *cp;
-
- i = nelem * size;
- if((cp = malloc(i)) != NULL)
- memset(cp,0,i);
- return cp;
- }
- /* Print free list map */
- memstat(argc,argv,envp)
- int argc;
- char *argv[];
- void *envp;
- {
- HEADER *p;
- unsigned long total = 0;
- int i = 0;
-
- for(p = base.s.ptr;p != &base;p = p->s.ptr){
- total += p->s.size * sizeof(HEADER);
- printf("%5lx %6lu",ptol(p),(long)p->s.size * ABLKSIZE);
- if(++i == 4)
- putchar('\n');
- else
- printf(" | ");
- }
- if(i != 0)
- putchar('\n');
- printf("heap base %lx size %lu avail %lu (%lu%%) coreleft %u\n",
- ptol((void *)heapbase),heapsize,total,100L*total/heapsize,coreleft());
- printf("allocs %lu frees %lu (diff %lu) mfails %lu garbage %lu\n",
- allocs,frees,allocs-frees,memfail,garbage);
- }
- #endif
-
-